package com.liujit.gateway.utils;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.net.NetUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.springframework.http.HttpHeaders;

import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;

/**
 * @description: Ip工具类
 * @author: liujun
 * @create: 2021/3/24 4:55 下午
 **/
@Slf4j
public class IpUtil {

    /**
     * 获取IP地址
     *
     * @param inetSocketAddress
     * @param httpHeaders
     * @return
     */
    public static String getIp(InetSocketAddress inetSocketAddress, HttpHeaders httpHeaders) {
        String[] headers = { "X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP",
                "HTTP_X_FORWARDED_FOR" };
        String ip;
        for (String header : headers) {
            ip = httpHeaders.getFirst(header);
            if (false == NetUtil.isUnknown(ip)) {
                return NetUtil.getMultistageReverseProxyIp(ip);
            }
        }
        ip = inetSocketAddress.getAddress().getHostAddress();
        return NetUtil.getMultistageReverseProxyIp(ip);
    }

    /**
     * 获取ip所在城市
     *
     * @param ip
     * @return
     */
    public static String getCityInfo(String ip) {
        try {
            String tmpDir = System.getProperties().getProperty("java.io.tmpdir");
            String dbPath = tmpDir + "ip.db";
            File file = new File(dbPath);
            InputStream inputStream = ResourceUtil.getStream("ip2region.db");
            FileUtils.copyInputStreamToFile(inputStream, file);
            //查询算法
            int algorithm = DbSearcher.BTREE_ALGORITHM;
            DbConfig config = new DbConfig();
            DbSearcher searcher = new DbSearcher(config, file.getPath());
            Method method = null;
            switch (algorithm) {
            case DbSearcher.BTREE_ALGORITHM:
                method = searcher.getClass().getMethod("btreeSearch", String.class);
                break;
            case DbSearcher.BINARY_ALGORITHM:
                method = searcher.getClass().getMethod("binarySearch", String.class);
                break;
            case DbSearcher.MEMORY_ALGORITYM:
                method = searcher.getClass().getMethod("memorySearch", String.class);
                break;
            }
            DataBlock dataBlock = null;
            if (Util.isIpAddress(ip) == false) {
                log.error("Error: Invalid ip address");
            }
            dataBlock = (DataBlock) method.invoke(searcher, ip);
            return dataBlock.getRegion();
        } catch (Exception e) {
            log.error("Error: Invalid ip address");
        }
        return null;
    }
}